/*
 * BPlusTreeC.h
 *
 *  Created on: 20-Nov-2011
 *      Author: janani
 */

/*Sept 13th 2011
 * Author: Janani
 *
 * LEAF NODE STRUCT
 _____________________________________\\_______________________________________
 | _______________ _____________       \\   _______________ _______________   |
 | |Key| RID ptr | |Key| RID ptr |		\\ 	|Key| RID ptr | |Key| RID ptr |   |
 | |___|_________| |___|_________|	 	 \\ |___|_________| |___|_________|   |
 |________________________________________\\ _________________________________|

 where,
 _______________
 |Key| RID ptr |
 |___|_________|		LUnit

 *
 *
 *
  ----------------------------------------------------------------------------------------------
 *
 *
 * INTERNAL NODE STRUCT
 ____________________\\______________________
 | _______________ ___\\___________________  |
 | ||Key||Key||Key||   \\  ||Key||Key||Key|| |
 | ||___||___||___||____\\ ||___||___||___|| |
 |_______________________\\ _________________|

  where,
  ______
  ||Key|
  ||___|		IUnit

 *
 *
 */


#ifndef BPLUSTREEC_H_
#define BPLUSTREEC_H_

#include "../globals/globals.h"
#include "../bufferManager/bufferManager.h"
//#include "../dbEngine/dbModule.h"
extern sysIndex* propertyObj ;
/*------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------My B Plus Tree NameSpace with associated structures ---------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------------------------------------------------*/


namespace BPlusTreeNS {

typedef struct IUnitStruct
{
	long ptr;
	char key[1];
}iUnit;

typedef struct LUnitStruct
{
	RID ridPtr;
	char key[1];
}lUnit;

typedef struct LeafNodeStruct
{
	int level;
	int numOfRecords;
	long prevLNodePtr;
	long nextLNodePtr;
	struct LUnitStruct lunit[1]; // Implying you can have a variable number of such lunits within a LNode
}leafNode;

typedef struct InternalNodeStruct
{
	int level;
	int numOfTrees;
	int numOfKeys;
	long prevINodePtr;
	struct IUnitStruct iunit[1];
}internalNode;

/*typedef struct NodeStruct
{
	bool isChanged;
	union
	{
			internalNode intNode;
			leafNode leaf;
	};
}NODE;*/

typedef struct keyPartStruct
		{
				char attributeName[50];
				char attributeType[20];
				int attributeSize;
		}keyPart;
/*------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*---------------------------------------------My B Plus Tree Class Definition ---------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------------------------------------------------*/
class BPlusTreeC
{
private :
		// member variables;

		internalNode* root;

		leafNode* leaf ; // for testing purposes


		int globPosition; // position to insert
		long tableDirPage;
		long ptrToPageContainingRootofTree;
		int isAscOrDesc;


		// size of elements
		int fanoutFactor;
		int leafFanoutFactor;
		int attributeCount;
	    int iUnitSize;
	    int keyUnitSize;
	    int lUnitSize;


	    /// Janani :)
		keyPart compositeKeyParts[2];

/*------------------------------------------------------------------------------------------------------------------------------------------------------*/
public:
	// Constructors & Destructors
	BPlusTreeC();
	virtual ~BPlusTreeC();

	// getters and setters

	int getAttributeCount () const
	{
		return this->attributeCount;
	}


	void setAttributeCount (int i)
	{
		this->attributeCount = i ;
	}

	int getIUnitSize () const
	{
		return this->iUnitSize;
	}

	void setIUnitSize ()
		{
		if (this->keyUnitSize == 0 )
		{
			setKeyUnitSize();
		}
			this->iUnitSize = LONG_SIZE + this->keyUnitSize;
			cout << endl << "The Internal Node's Iunit size is " << this->iUnitSize;
		}

	int getLUnitSize () const
		{
			return this->lUnitSize;
		}

	void setLUnitSize ()
		{
			if (this->keyUnitSize == 0 )
			{
				setKeyUnitSize();
			}
			this->lUnitSize = LONG_SIZE + INT_SIZE + this->keyUnitSize;

				cout << endl << "The Leaf Node's Lunit size is " << this->lUnitSize;
		}

	int getKeyUnitSize() const
	{
		return this->keyUnitSize;
	}

	void setKeyUnitSize ()
		{
				int count = this->getAttributeCount();
				for (int i =0 ; i < count ; i++)
										this->keyUnitSize += propertyObj->compositeKeyParts[i].attributeSize;
				cout << endl << "The key unit size is " << this->keyUnitSize;

		}


	int getFanoutFactor() const
		{
			return this->fanoutFactor;
		}

	void setFanoutFactor ()
			{
					// Page data size - the node header - sibling pointer divided by the size of the key and the pointer

					this->fanoutFactor = ((PAGEDATA_SIZE-INT_SIZE-INT_SIZE-INT_SIZE-LONG_SIZE-LONG_SIZE)/((LONG_SIZE+this->keyUnitSize)));
					cout << endl << "Fanout for a Node" << this->getFanoutFactor();
			}

	int getLeafFanoutFactor () const
			{
				return this->leafFanoutFactor;
			}


	void setLeafFanoutFactor ()
			{

					// Page data size - the node header - next pointer(Long) - previous pointer divided by the size of the key and the pointer

					this->leafFanoutFactor = ((PAGEDATA_SIZE-INT_SIZE-INT_SIZE-LONG_SIZE-LONG_SIZE)/((LONG_SIZE+INT_SIZE+this->keyUnitSize)));
					cout << endl << "Fanout for a LEAF Node" << this->getLeafFanoutFactor();
			}

/*------------------------------------------------------------------------------------------------------------------------------------------------------*/
	// Strict BPlusTree functions
public:

	void initBPlusTree();
	void delTree();

	void searchLeafNode(leafNode * n, char* searchKey);
	void searchInternalNode(internalNode * n, char* searchKey);

	char* generateCompositeKeyAsAString();

	void insertKeyIntoTree(RID *recordPointer, keyPart keyParts[], int colCount);
	void deleteKeyFromTree();
/*------------------------------------------------------------------------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------------------------------------------------------------------------*/
	void insertRecIntoTree();
	void deleteRecFromTree();

	void createLeafNode(leafNode ** l);
	void deleteLeafNode();

	void createInternalNode(internalNode ** n);
	void deleteInternalNode();

	void findLeafNodeToInsertInto();
	void splitNode();

	static void printNode(internalNode *, int , int );

	static void printLeafNode(leafNode *,int , int );

};//end of BPlusTreeC

} // end of BPlusTreeNS

#endif /* BPLUSTREEC_H_ */
//----------------------------------------------------------------------------------------------------------------------------------//----------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------------------

// Read more !!

/**
 *
 *
 *
 *\
 *\
 *\
 *\
 *\      public:
		//int add( const ElemType &elem );
		//void removeAt( int index );
		//void removeAt( int index, ElemType &removed );
		//void clear();
		//bool find( const KeyT &key, int &index ) const;
		//bool hasChilds() const;
		//bool isEmpty() const;
		//bool isFull() const;
		//int count() const;


 *\
 *\///
	/// Add new key:data pair
	bool add( const KeyT &key, const DataT &data );

	///
	/// Remove pair by key
	bool remove( const KeyT &key );

	///
	/// Remove pair by key and return associated data
	bool remove( const KeyT &key, DataT &data );

	///
	/// Find data by key, or return false if key was not found
	bool find( const KeyT &key, DataT &data );

	///
	/// Find all specified data
	template< class TChecker, class TContainer >
	bool search( TContainer &retList, const KeyT &startKey,
		bool preciseSearch, TChecker &condition );

	///
	/// Get all specified in container data
	template< class TContainer >
	bool getAll( TContainer &retList );

	///
	/// Change data which belongs to the key is specified
	void changeData( const KeyT &key, const DataT &newData );

	///
	/// Close BTree and release all occupied resources
	void close();



	int getMedian( NodeType *node, BTreeElement< KeyT, DataT > &elem );

	void splitNodeByKey( NodeType **fullNode, KeyT &key );
	bool splitNode( NodeType *node,
		BTreeElement< KeyT, DataT > &median, NodeType **nodeRight );

	NodeType* findNode( NodeType *node, const KeyT &key, int &retIndex,
		int &parentIndex, bool &found );

	bool rebalance( NodeType *node, int parentIndex );
	bool combine( NodeType *leftNode, NodeType *rightNode );
	bool pullOut( NodeType *node, int itemIndex );

	NodeType* rightMost( NodeType *subtree, KeyT &largestKey, DataT &largestData );
	NodeType* leftMost( NodeType *subtree, KeyT &smallestKey, DataT &smallestData );

	// Internal search methods
	template < class TChecker, class TContainer >
	bool allKeys( NodeType *node, TContainer &retList, int elemIndex,
		const KeyT &startKey, TChecker &condition );
	template < class TChecker, class TContainer >
	bool allKeys( NodeType *node, TContainer &retList, TChecker &condition );
	template< class TContainer >
	bool allKeys( NodeType *node, TContainer &retList );

 *
 *
 */


